package com.david.http.http

import com.david.http.BASE_URL
import com.david.http.BuildConfig
import com.david.http.http.convert.FlowCallAdapterFactory
import com.david.http.http.interceptor.HeaderInterceptor
import com.david.http.http.interceptor.HttpLoggingInterceptor
import com.david.http.http.interceptor.TokenInterceptor
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit

/**
 * example:
 * ref [com.david.http.http.method.test.IMethodTest]
 * ref [com.david.http.HttpTestMainActivity]
 * ref TestUrlConstant
 * retrofitHelper.create(IMainInterface::class.java).test()
 *                 .observe(this) {
 *                     Log.e("http", "result is $it")
 *                 }
 *
 *
 * token刷新逻辑：
 * 1.要求后台返回过期时间;
 * 2.每次请求后判断是否快过期；
 * 3.快过期则发送延时(时间为过期前的随机时间)任务更新token；
 *
 * 如：
 * public void checkToken(){
 * long tokenExpiredTime = PreferenceUtils.Companion.getInstance().getLong("token_expired_time");
 * if (System.currentTimeMillis() >= tokenExpiredTime - 600000) {//过期前10分钟内即更新
 * updateToken();
 * }
 * }
 *
 * public void updateToken(){
 *
 * }
 * 在request方法最后调用checkToken();
 */

object MyRetrofitHelper {
    private var okHttpClient: OkHttpClient
    private var retrofit: Retrofit

    init {
        val options = Options().baseUrl(BASE_URL)

        options.interceptors.add(HeaderInterceptor(mapOf("caqingyue" to "calala")))
        if (BuildConfig.DEBUG) {
            val logInter = HttpLoggingInterceptor()
            logInter.level = HttpLoggingInterceptor.Level.BODY
            options.interceptors.add(logInter)
        }

        options.interceptors.add(TokenInterceptor())

        okHttpClient = getOkhttpClient(options)
        retrofit = getRetrofit(okHttpClient, options)
    }


    private fun getOkhttpClient(options: Options): OkHttpClient {
        val okHttpClient = OkHttpClient.Builder()
            .connectTimeout(options.connectTimeout, TimeUnit.MILLISECONDS)
            .readTimeout(options.readTimeout, TimeUnit.MILLISECONDS)
            .writeTimeout(options.writeTimeout, TimeUnit.MILLISECONDS)
            .apply {
                for (interceptor in options.interceptors) {
                    addInterceptor(interceptor)
                }
                for (networkInterceptor in options.networkInterceptors) {
                    addNetworkInterceptor(networkInterceptor)
                }
            }
            .build()
        return okHttpClient
    }


    /**用于获取其他baseUrl的retrofit,example:
     * retrofitHelper.getRetrofit("http://192.168.1.104:8080").create(IMainInterface::class.java).test().observe(this) {
     *                 Log.e("http", "result is $it")
     *             }
     */
    fun getRetrofit(okHttpClient: OkHttpClient, options: Options): Retrofit {
        return Retrofit.Builder()
            .baseUrl(options.baseUrl)
            .client(okHttpClient)
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(FlowCallAdapterFactory.create())
            .build()
    }

    fun <T> create(service: Class<T>): T {
        return retrofit.create(service)
    }

    class Options {
        internal lateinit var baseUrl: String
        internal var connectTimeout = 10_000L
        internal var readTimeout = 10_000L
        internal var writeTimeout = 10_000L
        internal val interceptors = mutableListOf<Interceptor>()
        internal val networkInterceptors = mutableListOf<Interceptor>()

        fun baseUrl(baseUrl: String): Options {
            this.baseUrl = baseUrl
            return this
        }

        fun connectTimeout(connectTimeout: Long): Options {
            this.connectTimeout = connectTimeout
            return this
        }

        fun readTimeout(readTimeout: Long): Options {
            this.readTimeout = readTimeout
            return this
        }

        fun addInterceptor(interceptor: Interceptor): Options {
            interceptors += interceptor
            return this
        }

        fun addNetworkInterceptor(interceptor: Interceptor): Options {
            networkInterceptors += interceptor
            return this
        }
    }
}